home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / DeveloperLabs / Lab3 / Controller.m < prev    next >
Text File  |  1995-06-12  |  8KB  |  247 lines

  1. /*  Controller.m --- Main controller object for the TextLab program.
  2. **  Authors: Bruce Blumberg and Ali Ozer, NeXT Developer Support Group
  3. */
  4.  
  5. // Controller object is the central object in TextLab.  It manages the
  6. // windows, open/save panels, and menu commands. 
  7.  
  8. #import "Controller.h"
  9. #import "TextView.h"
  10. #import <appkit/Application.h>
  11. #import <objc/typedstream.h>
  12.  
  13. @implementation Controller
  14.  
  15. // We subclass the Controller "new" so that we can set the application's
  16. // delegate to point to the Controller object. This way open file
  17. // requests from the Workspace get routed to the Controller's 
  18. // appOpenFile:type: and appAcceptsAnotherFile methods.
  19.  
  20. + new
  21. {
  22.   self = [super new];
  23.   [NXApp setDelegate:self];
  24.   
  25.   // create instances of support objects
  26.   openReq = [OpenPanel new];
  27.   saveReq = [SavePanel new];
  28.   
  29.   return self;
  30. }
  31.  
  32. - showError: (char *)errorMessage
  33. {
  34.   NXRunAlertPanel (NULL, errorMessage,"OK",NULL,NULL);
  35. }
  36.  
  37. // newTextView: is invoked in response to a new empty window request. It
  38. // creates a new window containing a TextView. Note that we want new windows 
  39. // to be offset from each other by some amount; hence the use of wRect.
  40.  
  41. #define ORIGX 100.0
  42. #define ORIGY 100.0
  43. static NXRect wRect = {{ORIGX, ORIGY},{500.0,400.0}};
  44.  
  45. - newTextView:sender
  46. {   
  47.     id newTextView;
  48.     NXOffsetRect(&wRect, 20.0, -20.0);
  49.     if (wRect.origin.y < 0) {wRect.origin.y = ORIGY; wRect.origin.x = ORIGX;}
  50.     newTextView = [TextView newFrame:&wRect];
  51.     [[newTextView window] setDelegate:self];     
  52.     return self;
  53. }
  54.  
  55. // appAcceptsAnotherFile is an application delegate method which 
  56. // returns whether it is OK for the application to try to open more files
  57. // with the appOpenFile:type: method. TextLab can indeed open multiple
  58. // windows, so we return YES.
  59.  
  60. -(BOOL) appAcceptsAnotherFile:sender
  61. {
  62.   return (YES);
  63. }
  64.  
  65.  
  66. // appOpenFile:type: is called to open the specified file. It is normally
  67. // called by the Application object in response to open requests from the
  68. // Workspace. Here we also route the open requests from the OpenPanel
  69. // to this method (see openRequest:).
  70.  
  71. -(int) appOpenFile:(char *)fileName type:(char *)fileType
  72. {
  73.    return [self openFile:fileName];  
  74. }
  75.  
  76. // openRequest: opens a new file. It puts up a open panel, and, if the user
  77. // doesn't cancel, it reads the specified archive file. If the selected file
  78. // is not a proper archive file, then openRequest: will complain.
  79.  
  80. - openRequest:sender
  81. {
  82.     const char *fileName;
  83.     const char *const types[2] = {"tl", NULL};
  84.     int ok;
  85.  
  86.     if ([openReq runModalForTypes:types] && (fileName =[openReq filename])) {
  87.     [self openFile:fileName];
  88.     }
  89.     else
  90.     [self showError:"Not a valid textlab file."];
  91.     return self;
  92. }
  93.  
  94. -(int) openFile:(const char *)fileName
  95. {
  96.    id win;
  97.    NXTypedStream *typedStream;
  98.    
  99.     if(!(typedStream = NXOpenTypedStreamForFile(fileName,NX_READONLY))){
  100.     [self showError:"error on opening file"];
  101.     return NO;
  102.     }
  103.     else {
  104.     win = NXReadObject(typedStream);
  105.     NXCloseTypedStream(typedStream);
  106.     [win setTitle:fileName];
  107.         [[win display] makeKeyAndOrderFront:self];
  108.     return YES;
  109.     } 
  110. }
  111.  
  112.  
  113. // saveRequest: saves the current window under its default name (found in
  114. // the title bar). Note that if the title bar is empty or the default title
  115. // is "Untitled" then saveRequest: will put up a save panel, giving the user
  116. // a chance to specify a real title.
  117.  
  118. - saveRequest:sender
  119. {
  120.     const char *fileName;
  121.     id curWin = [NXApp mainWindow];
  122.  
  123.     if (curWin == nil) 
  124.     [self showError:"No active window to save."];
  125.     else {
  126.     // Check to see if the current window is titled and the title is not
  127.     // "Untitled". If so, save the file, else put up a save panel...
  128.     fileName = [curWin title];
  129.     if (strcmp (fileName, "Untitled"))
  130.         [self saveWindow:curWin inPath:fileName];
  131.     else [self saveInRequest:sender];
  132.     }
  133.     return self;
  134. }
  135.  
  136. // saveInRequest: gives the user a chance to save the current window
  137. // under a new name. 
  138.  
  139. - saveInRequest:sender
  140. {
  141.     const char *fileName;
  142.     id curWin;
  143.  
  144.     /*            EXERCISE #4a                 *
  145.     *    Add code to respond to an saveInRequest            *
  146.     *    Hint:  Use a SavePanel to get the file name and     *
  147.     *    directory where the document should be saved.        *
  148.     *    You will note that the saveReq instance variable    *
  149.     *    was initialized in the +new method of Controller    *
  150.     *    to point to a SavePanel. SavePanels will automatically     *
  151.     *    append an extension on the file name specified by the    *
  152.     *    the user if you have previously sent it the         *
  153.     *    setRequiredFileType: message passing it the appropriate *
  154.     *    extension. Once you have done this, you should send it a*
  155.     *    a method called runModalForDirectory:file: which    *
  156.     *    makes theSavePanel visible and which make it        *                    
  157.     *    a modal window. Once that method returns you can    *
  158.     *    query the SavePanel for the file name              *
  159.     *    selected (look in the spec sheets for SavePanel).    *
  160.     *    Assuming you used setRequiredFileType: earlier the file *
  161.     *    name returned will have the appropriate extension    *
  162.     *    Finally you should call the saveWindow:inPath:         *
  163.     *    method of Controller which will actually save the     *
  164.     *   document. Note the first argument to saveWindow is    *                     
  165.     *    the id of the window containing the document to be     *
  166.     *    saved. Look at the specSheets for the Application     *
  167.     *    object to see what method to use to get the id of the     *
  168.     *    current main window. In fact you will probably want to    *
  169.     *    get the id of the main window first thing in here so     *
  170.     *    you can use its title as the default file name for    *
  171.     *    the file in which the window will be stored        */
  172.     
  173.     return self;
  174. }
  175.  
  176.  
  177. // saveWindow writes a window out the archive file whose name is specified
  178. // by the second argument. The title of the current window is also set 
  179. // accordingly.
  180.  
  181. - saveWindow:(id)win inPath:(const char *)name
  182. {    
  183.    NXTypedStream *typedStream;
  184.     
  185.    [win setTitle:name];
  186.     
  187.     /*            EXERCISE #4b                 *
  188.     *    Add code to store win and its contents            *
  189.     *    in an file called name.Hint: you will want to         *
  190.     *   use typedStreams to write out the window and its    *
  191.     *    contents. The code to do this will look similar to the     *
  192.     *    code in openFile: so be sure to look at that code. You    *
  193.     *    will need to do 3 things. 1) Open a typedStream on a     *
  194.     *    file named name using NXOpenTypedStreamForFile()    *
  195.     *    2) Write out the window to the typedStream using    *
  196.     *    NXWriteRootObject(). 3) Close the typedStream.        */
  197.     
  198.     return self;
  199. }
  200.  
  201. // Printing is rather simple; just send printPSCode: to the text view
  202. // you wish to print. The print panel will automatically pop up and unless
  203. // the user cancels the printout the text view will be printed.
  204.  
  205. - printRequest:sender
  206. {
  207.     /*            EXERCISE 5                 *
  208.     *    Add code to assign curText to point to            *
  209.     *    view which should be printed. Hint: it is the        *
  210.     *    docView of the TextView in the application's        *
  211.     *    mainWindow. Look at the spec sheets for the        *
  212.     *    Application class to see how to get the id of        *
  213.     *    the current main window                    */
  214.  
  215.     id curText = nil;
  216.  
  217.     if (curText == nil) [self showError:"No active window to print."];
  218.     else {
  219.     /*        EXERCISE 5b                *
  220.     *     Add code to print view                *
  221.     *                            *
  222.     *                            */ 
  223.     }
  224.     return self;
  225. }
  226.  
  227. // closeRequest closes the current window by simulating a click on the
  228. // closebutton. A check should probably be added to give the user the 
  229. // option of saving the window before closing
  230.  
  231. - closeRequest:sender
  232. {
  233.    [[NXApp mainWindow] performClose:sender];
  234.    return self;
  235. }
  236.  
  237. // This method will get called before a window is closed and
  238. // will give the user an opportunity to save their file. It then returns
  239. // self indicating that the window may be closed.
  240.  
  241. - windowWillClose:(id)whichWin
  242. {
  243.     return self;
  244. }
  245.     
  246. @end
  247.